""" PsyBlockGame main window """

from PyQt4.QtCore import SIGNAL, SLOT, QTranslator
from PyQt4.QtGui import *
from PsyBlockGame.UI.MainWindow import Ui_MainWindow
from PsyBlockGame.Game import Game
from PsyBlockGame.Settings import GameSettings
from PsyBlockGame.ApplicationConfig import ApplicationConfig
from PsyBlockGame.TestRecord import TestRecord, RecordBase
from PsyBlockGame.GameTimer import GameTimer
from PsyBlockGame.UserStatistics import UserStatistics
import PsyBlockGame

class GameWindow(QMainWindow):
    def __init__(self):
        super(GameWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.board.resizeEvent = self.boardResizeEvent

        self.config = ApplicationConfig()
        self.config.load()

        self.startTimer(0)

        if not PsyBlockGame.IS_DEMO:
            self.enableAdminMode(False)

        self.ui.board.setRenderHint(QPainter.Antialiasing)
        self.game = Game(self.ui.board)
        self.game.config = self.config.currentConfig.copy()
        self.connect(self.game, SIGNAL('onRoundStarted()'), self.onRoundStarted)
        self.connect(self.game, SIGNAL('onFlyAwayStarted(int)'), self.onFlyAwayStarted)
        self.connect(self.game, SIGNAL('onFlyAwayTimeout()'), self.onFlyAwayTimeout)

        self.results = RecordBase()
        self.results.load()
        
        self.currentUser = None
        self.isRoundStarted = False
        self.timer = GameTimer()
        self.totalTime = GameTimer()

        self.englishTranslation = QTranslator()
        self.russianTranslation = QTranslator()
        self.russianTranslation.load(r":\game\localization.qm")

        self.isInitData = False
        self.setEnglishLang(self.config.isEnglishLang)

    def enableAdminMode(self, enable = True):
        self.ui.actionFileLogin.setVisible(not enable)
        self.ui.actionFileLogOut.setVisible(enable)

        self.ui.menuBar.clear()
        self.ui.menuBar.addMenu(self.ui.menuFile)
        if enable:
            self.ui.menuBar.addMenu(self.ui.menuTools)

    #
    # UI Callbacks
    #
    def onStart(self):
        user = self.getUserName()
        if user is None:
            return

        self.game.stop()
        self.game.config = self.config.currentConfig.copy()

        self.currentUser = TestRecord(user)
        print("START:", user)

        self.ui.startBtn.setEnabled(False)

        self.usedKeys = { p.key : index for index, p in enumerate(self.game.config.figures) }

        self.totalTime.start()
        self.isRoundStarted = False
        self.game.startLevel()

    def onLogin(self):
        layout = QGridLayout()
        layout.addWidget(QLabel(self.tr("Enter password:")), 0, 0)
        password = QLineEdit()
        password.setEchoMode(QLineEdit.Password)
        password.setMinimumWidth(150)
        layout.addWidget(password, 0, 1)

        box = QDialogButtonBox()
        box.addButton(QDialogButtonBox.Ok)
        box.addButton(QDialogButtonBox.Cancel)
        layout.addWidget(box, 1, 1)

        dlg = QDialog(self)
        dlg.setWindowTitle(self.tr("Login"))
        dlg.setLayout(layout)

        dlg.connect(box, SIGNAL('accepted()'), SLOT('accept()'))
        dlg.connect(box, SIGNAL('rejected()'), SLOT('reject()'))

        if dlg.exec_() != QDialog.Accepted:
            return

        if password.text() != self.config.adminPassword:
            QMessageBox.critical(self, self.tr("Oops"),
                self.tr("Wrong password"))

            if not PsyBlockGame.IS_DEMO:
                return

        self.enableAdminMode()

    def onLogout(self):
        if not PsyBlockGame.IS_DEMO:
            self.enableAdminMode(False)

    def onChangePassword(self):
        layout = QGridLayout()

        def makePwdEdit(text, row):
            layout.addWidget(QLabel(text), row, 0)

            pwd = QLineEdit()
            pwd.setEchoMode(QLineEdit.Password)
            layout.addWidget(pwd, row, 1)
            return pwd
        
        oldPassword = makePwdEdit(self.tr("Old password:"), 0)
        newPassword = makePwdEdit(self.tr("New password:"), 1)
        checkPassword = makePwdEdit(self.tr("Repeat:"), 2)

        box = QDialogButtonBox()
        box.addButton(QDialogButtonBox.Ok)
        box.addButton(QDialogButtonBox.Cancel)
        layout.addWidget(box, 3, 1)

        dlg = QDialog(self)
        dlg.setWindowTitle(self.tr("Change password"))
        dlg.setLayout(layout)

        def onAccept():
            check = lambda x : len(x.text()) == 0

            if check(oldPassword) or check(newPassword) and check(checkPassword):
                return                

            if newPassword.text() != checkPassword.text():
                QMessageBox.critical(self, self.tr("Oops"), self.tr("Please enter new password in both fields"))
                return

            if oldPassword.text() != self.config.adminPassword:
                QMessageBox.critical(self, self.tr("Oops"), self.tr("Wrong password"))
                return

            dlg.accept()

        dlg.connect(box, SIGNAL('accepted()'), onAccept)
        dlg.connect(box, SIGNAL('rejected()'), SLOT('reject()'))

        if dlg.exec_() != QDialog.Accepted:
            return

        self.config.adminPassword = newPassword.text()
        self.config.save()

    def onSettings(self):
        dlg = GameSettings(self.config, self)
        dlg.exec_()

    def onStatistics(self):
        dlg = UserStatistics(self.results, self)
        dlg.exec_()

    def onEnglishLanguage(self):
        self.setEnglishLang()

    def onRussianLanguage(self):
        self.setEnglishLang(False)

    #
    # System events
    #
    def boardResizeEvent(self, e):
        size = self.ui.board.geometry()
        self.ui.board.setSceneRect(size.x() - size.width() / 2, size.y() - size.height() / 2, size.width(), size.height())

    def timerEvent(self, e):
        self.game.update()

    def closeEvent(self, e):
        if self.currentUser is None:
            return

        if QMessageBox.No == QMessageBox.warning(self, self.tr("Oops..."),
            self.tr("Do you want to stop current test?"),
            QMessageBox.Yes | QMessageBox.No):
            e.ignore()
            return

        self.currentUser.addResultInterrupted()
        self.finishResults()

    def keyPressEvent(self, e):
        time = self.timer.time()

        if not self.timer.isStarted():
            if self.isRoundStarted:
                self.timer.stop()
                self.isRoundStarted = False
                self.currentUser.addResultBeforeStart()
                print("TOO EARLY")
                self.startNewRound()
            return

        try:
            pressed = QKeySequence(e.key()).toString()
            print(pressed)
        except:
            return

        if pressed not in self.usedKeys:
            return

        if self.usedKeys[pressed] != self.figureIndex:
            self.currentUser.addResultWrong(time)
            print("WRONG", time)
        else:
            self.currentUser.addResultSuccess(time)
            print("SUCCESS", time)

        self.timer.stop()
        self.isRoundStarted = False
        self.startNewRound()
        
    #
    # Game
    #
    def onRoundStarted(self):
        self.isRoundStarted = True

    def onFlyAwayStarted(self, index):
        self.figureIndex = index
        self.timer.start()
        print("START")

    def onFlyAwayTimeout(self):
        self.timer.stop()
        self.isRoundStarted = False
        self.currentUser.addResultTimeout()
        print("TIMEOUT")
        self.startNewRound()

    def finishResults(self):
        self.results.addRecord(self.currentUser, self.config.lastName)
        self.results.save()

        self.currentUser = None
        self.game.stop()
        self.ui.startBtn.setEnabled(True)
        
    #
    # Misc
    #
    def setEnglishLang(self, enable = True):
        if self.isInitData:
            return

        self.isInitData = True
        self.ui.actionEnglish.setChecked(enable)
        self.ui.actionRussian.setChecked(not enable)
        self.isInitData = False

        self.config.isEnglishLang = enable
        self.config.save()

        from PsyBlockGame import qApp

        if enable:
            qApp.removeTranslator(self.russianTranslation)
        else:
            qApp.installTranslator(self.russianTranslation)

        self.ui.retranslateUi(self)

    def startNewRound(self):
        if not self.totalTime.expired(self.game.config.gameTime * 60):
            self.game.startRound()
            return

        self.finishResults()

        QMessageBox.information(self, self.tr("Thank you"), self.tr("Test finished"))

    def getUserName(self):
        layout = QGridLayout()
        layout.addWidget(QLabel(self.tr("Enter your name:")), 0, 0, 1, 1)
        name = QLineEdit()
        name.setMinimumWidth(200)
        layout.addWidget(name, 0, 1, 1, 2)
        box = QDialogButtonBox()
        box.addButton(QDialogButtonBox.Ok)
        box.addButton(QDialogButtonBox.Cancel)
        layout.addWidget(box, 1, 0, 1, -1)

        dlg = QDialog(self)
        dlg.setWindowTitle(self.tr("Start test"))
        dlg.setLayout(layout)

        def onAccept():
            if len(name.text()) > 0:
                dlg.accept()
        
        dlg.connect(box, SIGNAL('accepted()'), onAccept)
        dlg.connect(box, SIGNAL('rejected()'), SLOT('reject()'))

        if dlg.exec_() == QDialog.Accepted:
            return name.text()
        
        return None

